import CryptoJS from 'crypto-js';
import { UUID } from 'uuid-generator-ts';
import { systemConfig,user } from '@/store';
import { SM4,SM2 } from 'gm-crypto';
import { sm2} from 'sm-crypto';
import { Session } from '@/utils/storage';
const LOCAL_REFRESHTOKEN_NAME = import.meta.env.VITE_LOCAL_REFRESHTOKEN_NAME as string;
const LOCAL_TOKEN_NAME = import.meta.env.VITE_LOCAL_TOKEN_NAME as string;
/* 常用加解密 */
//MD5加密
export function MD5(data: string | CryptoJS.lib.WordArray) {
	return CryptoJS.MD5(data).toString();
}
//BASE64加解密
export function encryptBASE64(data: string) {
	return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data));
}
export function decryptBASE64(cipher: string) {
	return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8);
}
//AES加解密
export function encryptAES(data: string | CryptoJS.lib.WordArray, secretKey: string) {
	if (!secretKey) {
		secretKey = decryptBASE64(systemConfig.defaultAESKey);
	}
	const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7,
	});
	return result.toString();
}

export function decryptAES(cipher: string | CryptoJS.lib.CipherParams, secretKey: string) {
	if (!secretKey) {
		secretKey = decryptBASE64(systemConfig.defaultAESKey);
	}
	const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7,
	});
	return CryptoJS.enc.Utf8.stringify(result);
}
function gotoLogin(){

	Session.remove(LOCAL_TOKEN_NAME);
	Session.remove(LOCAL_REFRESHTOKEN_NAME);
		
}
export function decryptSM4(data: string , secretKey: any) {
	let key='';
	if (!secretKey) {
		const token = Session.get(LOCAL_TOKEN_NAME);
		if(token){
			if(user.defaultSM4Key){
				secretKey=user.defaultSM4Key
			}else{
				let secretStr=Session.get("USERSECRET");
				if(secretStr){
					let secret=JSON.parse(decryptSM4(secretStr,systemConfig.defaultSM4Key));
					secretKey=secret.defaultSM4Key
					user.setUserSecret(secret);
				}else{
					gotoLogin()
				}
			}
		}else{
			key = systemConfig.defaultSM4Key;
		}
	}else{
		key=secretKey
	}
	const result = SM4.decrypt(data, key, {
		inputEncoding: 'base64',
		outputEncoding: 'utf8'
	});
	return result;
}

export function encryptSM4(data: string , secretKey: any) {
	let key='';
	if (!secretKey) {
		const token = Session.get(LOCAL_TOKEN_NAME);
		if(token){
			if(user.defaultSM4Key){
				secretKey=user.defaultSM4Key
			}else{
				let secretStr=Session.get("USERSECRET");
				if(secretStr){
					let secret=JSON.parse(decryptSM4(secretStr,systemConfig.defaultSM4Key));
					secretKey=secret.defaultSM4Key
					user.setUserSecret(secret);
				}else{
					gotoLogin()
				}
			}
		}else{
			key = systemConfig.defaultSM4Key;
		}
	}else{
		key=secretKey
	}
	const result = SM4.encrypt(data, key, {
		inputEncoding: 'utf8',
		outputEncoding: 'base64'
	});
	return result;
}
export function decryptSM2(data: string , secretKey: any) {
	if (!secretKey) {
		const token = Session.get(LOCAL_TOKEN_NAME);
		if(token){
			if(user.defaultSM2PrivateKey){
				secretKey=user.defaultSM2PrivateKey
			}else{
				let secretStr=Session.get("USERSECRET");
				if(secretStr){
					let secret=JSON.parse(decryptSM4(secretStr,systemConfig.defaultSM4Key));
					secretKey=secret.defaultSM2PrivateKey
					user.setUserSecret(secret);
				}else{
					gotoLogin()
				}
			}
		}else{
			secretKey = systemConfig.defaultSM2PrivateKey;
		}
	}
	try{
		//判断返回的密文是否是数组
		let result='';
		if (data.startsWith("[")) {
			const encryptedSegments = JSON.parse(data);
			for (const encryptedSegment of encryptedSegments) {
				let segment=encryptedSegment;
				if (encryptedSegment.substr(0, 2) == '04') {
					segment = encryptedSegment.substr(2);
				}
				/* const decryptedSegment = SM2.decrypt(segment, secretKey, {
					inputEncoding: 'hex',
					outputEncoding: 'utf8'
				});*/
				const decryptedSegment = sm2.doDecrypt(segment, secretKey);
				result += decryptedSegment;
			}
		}else{
			if (data.substr(0, 2) == '04') {
				data = data.substr(2);
			}
			/*const decryptedSegment = SM2.decrypt(data, secretKey, {
				inputEncoding: 'hex',
				outputEncoding: 'utf8'
			});*/
			const decryptedSegment = sm2.doDecrypt(data, secretKey);
			result += decryptedSegment;
		}
		return result;
	}catch(e){
		console.error("解析异常：",e)
		return data;
	}
	
	
}

export function encryptSM2(data: string , secretKey: any) {
	if (!secretKey) {
		const token = Session.get(LOCAL_TOKEN_NAME);
		if(token){
			if(user.defaultSM2PublicKey){
				secretKey=user.defaultSM2PublicKey
			}else{
				let secretStr=Session.get("USERSECRET");
				if(secretStr){
					let secret=JSON.parse(decryptSM4(secretStr,systemConfig.defaultSM4Key));
					secretKey=secret.defaultSM2PublicKey
					user.setUserSecret(secret);
				}else{
					gotoLogin()
				}
			}
			
		}else{
			secretKey = systemConfig.defaultSM2PublicKey;
		}
		
	}
	try{
		if(!systemConfig.splitFlag){
			/*return '04'+SM2.encrypt(data, secretKey,{
			   inputEncoding: 'utf8',
			   outputEncoding: 'hex'
			});*/
			return '04'+sm2.doEncrypt(data, secretKey);
		}else{
			const segmentSize=2560*4;
			const encryptedSegments = [];
			for (let i = 0; i < data.length; i += segmentSize) {
				const segment = data.slice(i, i + segmentSize);
				/* const encryptedSegment = SM2.encrypt(segment, secretKey,{
				   inputEncoding: 'utf8',
				   outputEncoding: 'hex'
				});*/
				const encryptedSegment = sm2.doEncrypt(segment, secretKey);
				encryptedSegments.push("04"+encryptedSegment);
			}
			return JSON.stringify(encryptedSegments);
		}
	}catch(e){
		console.error("加密异常：",e)
		return data;
	}
}

export function isIE() {
	const bw = window.navigator.userAgent;
	const compare = (s: any) => bw.indexOf(s) >= 0;
	const ie11 = (() => 'ActiveXObject' in window)();
	return compare('MSIE') || ie11;
}

/**
 * Remove loading animate
 * @param id parent element id or class
 * @param timeout
 */
export function removeLoadingAnimate(id = '', timeout = 1500) {
	if (id === '') {
		return;
	}
	setTimeout(() => {
		document.body.removeChild(<any>document.getElementById(id));
	}, timeout);
}
/**
 * Remove an item from an array.
 */
export function remove(arr: any[], item: any) {
	if (arr.length) {
		const index = arr.indexOf(item);
		if (index > -1) {
			return arr.splice(index, 1);
		}
	}
}
export function isRegExp(v: any) {
	return _toString.call(v) === '[object RegExp]';
}
export interface BrowerModel {
	browserVersion: string | number;
	browserType: string;
}
/*
 * 获取浏览器版本信息
 */
export function getBrowerInfo(): BrowerModel {
	const userAgent: any = window.navigator.userAgent.toLowerCase();
	let browserType: string = '';
	let browserVersion: string | number = '';
	// 浏览器类型-IE
	if (userAgent.match(/msie/) != null || userAgent.match(/trident/) != null) {
		browserType = 'ie';
		browserVersion = getIeVersion();
	} else if (userAgent.match(/opera.([\d.]+)/)) {
		// 欧朋
		browserType = 'opr';
		browserVersion = getOperaVersion(userAgent);
	} else if (userAgent.indexOf('ubrowser') > 0) {
		browserType = 'uc';
		browserVersion = userAgent.match(/ubrowser\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('bidubrowser') > 0) {
		// 百度
		browserType = 'baidu';
		browserVersion = userAgent.match(/bidubrowser\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('metasr') > 0 || userAgent.indexOf('se 2.x') > 0) {
		// 搜狗
		browserType = 'metasr';
		// browserVersion =  userAgent.match(/metasr\/([\d.]+)/)[1]
	} else if (userAgent.indexOf('tencenttraveler') > 0) {
		browserType = 'qq';
		browserVersion = userAgent.match(/tencenttraveler\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('qqbrowser') > 0) {
		browserType = 'qq';
		browserVersion = userAgent.match(/qqbrowser\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('maxthon') > 0) {
		// 遨游
		browserType = 'maxthon';
		browserVersion = userAgent.match(/maxthon\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('firefox') > 0) {
		// 火狐
		browserType = 'firefox';
		browserVersion = userAgent.match(/firefox\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('edge') > 0) {
		// edge
		browserType = 'edge';
		browserVersion = userAgent.match(/edge\/([\d.]+)/)[1];
	} else if (userAgent.indexOf('chrome') > 0) {
		// 谷歌/360
		if (validate360('type', 'application/x360mmplugin')) {
			browserType = '360';
			// browserVersion =  userAgent.match(/chrome\/([\d.]+)/)[1]
		} else {
			browserType = 'chrome';
			browserVersion = userAgent.match(/chrome\/([\d.]+)/)[1];
		}
	} else if (userAgent.indexOf('Safari') > -1) {
		// 苹果
		browserType = 'safari';
		browserVersion = userAgent.match(/version\/([\d.]+)/)[1];
	} else {
		browserType = 'other';
	}
	let browser: BrowerModel = { browserType: browserType, browserVersion: browserVersion };
	return browser;
}
/*
 * 判断是否为360浏览器
 */
export function validate360(option: string, value: string) {
	const mimeTypes: any = window.navigator.mimeTypes;
	for (const mt in mimeTypes) {
		if (mimeTypes[mt][option] === value) {
			return true;
		}
	}
	return false;
}
/*
 * 获取IE浏览器版本
 */
export function getIeVersion() {
	const IEMode = document.DOCUMENT_NODE;
	const rMsie = /(msie\s|trident.*rv:)([\w.]+)/;
	const ma = window.navigator.userAgent.toLowerCase();
	const match: any = rMsie.exec(ma);
	try {
		return match[2] + '';
	} catch (e) {
		return IEMode + '';
	}
}
/*
 * 获取oper浏览器版本
 */
export function getOperaVersion(userAgent: any) {
	try {
		let s = userAgent.match(/opera\/([\d.]+)/)[1];
		let version = s[1].split('.');
		return version[0];
	} catch (e) {
		return 0;
	}
}
export function uuid() {
	const uuid = new UUID();
	return uuid.getDashFreeUUID();
}
export function formtojson(params: any) {
	var values: any = {};
	for (var item in params) {
		values[item] = params[item];
	}
	return values;
}
// eslint-disable-next-line no-unused-vars
export function loop(data: any[], key: any, callback: (arg0: any, arg1: any, arg2: any) => any) {
	data.forEach((item, index, arr) => {
		if (item.key === key) {
			return callback(item, index, arr);
		}
		if (item.children) {
			return loop(item.children, key, callback);
		}
	});
}
export function loopParentKey(data: any[], value: any, keys: any[]) {
	let flag = false;
	data.forEach((item) => {
		let itemFlag = false;
		if (item.title && item.title.indexOf(value) > -1) {
			itemFlag = true;
		}
		if (item.children) {
			const childFlag = loopParentKey(item.children, value, keys);
			if (childFlag) {
				itemFlag = true;
			}
		}
		if (itemFlag) {
			flag = true;
			keys.push(item.key);
		}
	});
	return flag;
}
export function loopLeafKey(data: any[], keys: any[]) {
	// 获取所有选中数据
	data.forEach((item) => {
		if (item.children) {
			return loopLeafKey(item.children, keys);
		} else {
			keys.push(item.key);
		}
	});
}
export function loopKey(data: any[], keys: any[]) {
	// 获取所有选中数据
	data.forEach((item) => {
		keys.push(item.key);
		if (item.children) {
			return loopKey(item.children, keys);
		}
	});
}
export function loopExpandCheck(data: any[], checkedKeys: any[], expandedKeys: any[]) {
	data.forEach((item) => {
		expandedKeys.push(item.key);
		if (item.children) {
			return loopExpandCheck(item.children, checkedKeys, expandedKeys);
		} else {
			checkedKeys.push(item.key);
		}
	});
}
//获取后端返回需要展开的节点
export function loopExpandKeys(data: any[], expandedKeys: any[]) {
	data.forEach((item) => {
		if (item.expanded) {
			expandedKeys.push(item.key);
		}
		if (item.children) {
			return loopExpandKeys(item.children, expandedKeys);
		}
	});
}
/***
 * 时间搓 格式化
 */
export function formatDate(datetime: string | number | Date) {
	const date = new Date(datetime); // 时间戳为10位需*1000，时间戳为13位的话不需乘1000
	const year = date.getFullYear();
	const month = ('0' + (date.getMonth() + 1)).slice(-2);
	const sdate = ('0' + date.getDate()).slice(-2);
	const hour = ('0' + date.getHours()).slice(-2);
	const minute = ('0' + date.getMinutes()).slice(-2);
	const second = ('0' + date.getSeconds()).slice(-2);
	// 拼接
	var result = year + '-' + month + '-' + sdate + ' ' + hour + ':' + minute + ':' + second;
	// 返回
	return result;
}
/**
 * 下划线转驼峰
 * @param string
 * @returns {*}
 */
export function underLine2CamelCase(string: string) {
	return string.replace(/_([a-z])/g, function (all, letter) {
		return letter.toUpperCase();
	});
}

export function isDef(v: null | undefined) {
	return v !== undefined && v !== null;
}
export function isEmptyStr(value: string | null | undefined) {
	let str;
	if (value == null || value == undefined) {
		str = value;
	} else {
		str = value + '';
	}
	if (str == null || str == 'null' || str == undefined || str == 'undefined' || str.match(/^[\s]*$/)) {
		return true;
	} else {
		return false;
	}
}
/**
 * @description   判断数据是否为网址(URL),请传入满足http标准协议的链接
 * @param {String} str_data 待校验的数据
 * @param {Boolean} flag 是否使用严格模式,默认为false
 * @returns {Boolean}, true:是网址
 **/
export function isUrl(str_data: string, flag: boolean) {
	flag = flag || false;
	let regular =
		/^\b(((https?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|asia|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\@&?=+,.!\/~%\$]*)?)$/i;
	let regular2 = /^((https?|ftp):\/\/)(www\.)?\S{0,30}\.\S+$/i;

	if (regular2.test(str_data) && !flag) {
		return true;
	} else if (regular.test(str_data) && flag) {
		return true;
	} else {
		return false;
	}
}
/***获取url上的参数 */
export function getQueryString(name: string) {
	const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
	const search = window.location.search.split('?')[1] || '';
	if (search) {
		const r = search.match(reg) || [];
		return r[2];
	} else {
		return null;
	}
}
export function deepClone(obj: any) {
	let newobj: any = Array.isArray(obj) ? [] : {};
	//constructor 属性返回对创建此对象的数组函数的引用。创建相同类型的空数据
	if (typeof obj !== 'object') {
		return;
	} else {
		for (let i in obj) {
			if (typeof obj[i] === 'object' && obj[i]) {
				//判断对象的这条属性是否为对象
				newobj[i] = deepClone(obj[i]); //若是对象进行嵌套调用
			} else {
				newobj[i] = obj[i];
			}
		}
	}
	return newobj; //返回深度克隆后的对象
}
const _toString = Object.prototype.toString;

// 驼峰转换下划线
export function toLine(name: string) {
	if(!name){
		return name;
	}
	return name.replace(/([A-Z])/g, '_$1').toLowerCase();
}
export function isValidKey(key: string | number | symbol, object: object): key is keyof typeof object {
	return key in object;
}
